﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SCG.SolarVengeanceEngine;
using SCG.WinForms;

namespace SCG.SolarVengeance
{
    public partial class StarShipPanel : BasePanel
    {
        //constructors
        public StarShipPanel()
            : base()
        {
            InitializeComponent();
        }

        //ensure proper sizing
        public override void Initialize()
        {
            elastic.ForceResize();
        }

        //update impulse
        public override void ImpulseUpdate()
        {
            List<StarShip> lst = GamePage.ShipsSelected;
            if (lst.Count == 0)
            {
                GamePage.SidePanelMode = SidePanels.Blank;
                return;
            }
            StarShip ship = lst[0];

            //name and owner
            if (lst.Count > 1)
                lblName.Text = lst.Count + " StarShips";
            else
            {
                GamePage.SurfaceCursor = ship.Location;
                if (ship.DiscoveredByCurrentPlayer)
                    lblName.Text = ship.Name;
                else
                    lblName.Text = "StarShip";
            }
            lblName.ForeColor = ship.Owner.Color.ToColor();
            lblOwner.Text = "Owner: " + ship.Owner.Name;
            lblOwner.ForeColor = lblName.ForeColor;
            picGlyph.Image = (Image)ship.Owner.Glyph;

            //single starship stats
            if (lst.Count == 1 && lst[0].DiscoveredByCurrentPlayer)
            {
                lblEngineValue.Text = ship.EngineStatLabel;
                if (ship.Engines == ship.MaxEngines)
                    lblEngineValue.ForeColor = Color.Lime;
                else if (ship.Engines >= ship.MaxEngines / 2)
                    lblEngineValue.ForeColor = Color.Yellow;
                else
                    lblEngineValue.ForeColor = Color.Red;
                ShowControls(elastic, 1, true);
                if (ship.ShipType.GetPrimarySystemName() == "")
                {
                    lblPrimary.Visible = false;
                    lblPrimaryValue.Visible = false;
                }
                else
                {
                    lblPrimary.Text = ship.ShipType.GetPrimarySystemName();
                    lblPrimaryValue.Text = ship.PrimarySystemStatLabel;
                    if (ship.Value == ship.MaxValue)
                        lblPrimaryValue.ForeColor = Color.Lime;
                    else if (ship.Value >= ship.MaxValue / 2)
                        lblPrimaryValue.ForeColor = Color.Yellow;
                    else
                        lblPrimaryValue.ForeColor = Color.Red;
                    lblPrimary.Visible = true;
                    lblPrimaryValue.Visible = true;
                }
            }
            else
                ShowControls(elastic, 1, false);

            //orders?
            if (ship.OwnedByCurrentPlayer)
            {
                //determine what orders the selected ships are able to accept
                _ordersVisible.Clear();
                CheckOrderType(OrderType.Patrol);
                CheckOrderType(OrderType.Escort);
                CheckOrderType(OrderType.Defend);
                CheckOrderType(OrderType.Transport);
                CheckOrderType(OrderType.Unload);
                CheckOrderType(OrderType.TugRelease);
                CheckOrderType(OrderType.GravRelease);
                CheckOrderType(OrderType.CreateGate);
                CheckOrderType(OrderType.Detonate);
                CheckOrderType(OrderType.SetViewPoint);
                CheckOrderType(OrderType.ShipBuildStarShip);
                CheckOrderType(OrderType.Launch);
                CheckOrderType(OrderType.EjectUDO);

                //see if we need to reconstruct the button panel
                bool regenButtons = _ordersVisible.Count != pnlOrders.Controls.Count;
                if (!regenButtons)
                    for(int i = 0; i < _ordersVisible.Count; i++)
                        if (((int)_ordersVisible[0]).ToString() != pnlOrders.Controls[i].Tag as string)
                        {
                            regenButtons = true;
                            break;
                        }

                //regenerate the buttons
                if (regenButtons)
                {
                    for (int n = pnlOrders.Controls.Count - 1; n >= 0; n--)
                    {
                        Button ctl = pnlOrders.Controls[n] as Button;
                        ctl.Click -= OrderClicked;
                        pnlOrders.Controls.Remove(ctl);
                    }
                    int x = 0;
                    int y = 0;
                    foreach (OrderType ot in _ordersVisible)
                    {
                        Button btn = new Button();
                        btn.Text = ot.ToDisplayName();
                        btn.Tag = ot;
                        btn.Dock = DockStyle.Fill;
                        btn.FlatStyle = FlatStyle.Flat;
                        btn.ForeColor = Color.Aqua;
                        btn.BackColor = Color.Black;
                        btn.FlatAppearance.BorderColor = Color.Aqua;
                        btn.Font = lblHelp.Font;
                        btn.Click += OrderClicked;
                        pnlOrders.Controls.Add(btn, x, y);
                        x++;
                        if (x == 2)
                        {
                            x = 0;
                            y++;
                        }
                    }
                }
                ShowControls(elastic, 2, true);

                //show current orders
                if (lst.Count == 1)
                {
                    if (ship.Order == null)
                    {
                        lblCurrentOrders.Text = "None";
                        btnClearOrders.Visible = false;
                    }
                    else
                    {
                        lblCurrentOrders.Text = ship.Order.ToString();
                        btnClearOrders.Visible = ship.CanExecuteOrder(OrderType.ClearOrders);
                    }
                }
                else
                {
                    if (GamePage.ShipsSelected.HasOrders)
                    {
                        if (GamePage.ShipsSelected.HaveSameOrders)
                            lblCurrentOrders.Text = ship.Order.ToString();
                        else
                            lblCurrentOrders.Text = "Various";
                        btnClearOrders.Visible = GamePage.ShipsSelected.CanExecuteOrder(OrderType.ClearOrders);
                    }
                    else
                    {
                        lblCurrentOrders.Text = "None";
                        btnClearOrders.Visible = false;
                    }
                }

                //attack adjacent
                if (GamePage.ShipsSelected.CanExecuteOrder(OrderType.AttackAdjacent))
                {
                    cbAttackAdjacent.Visible = true;
                    _ignoreAttackAdjacent = true;
                    cbAttackAdjacent.Checked = GamePage.ShipsSelected.AutoAttack;
                    _ignoreAttackAdjacent = false;
                }
                else
                    cbAttackAdjacent.Visible = false;
            }
            else
                ShowControls(elastic, 2, false);

            Refresh();
        }

        //see if the ships can execute an order, if so add it to the list
        private void CheckOrderType(OrderType ot)
        {
            if (GamePage.ShipsSelected.CanExecuteOrder(ot))
                _ordersVisible.Add(ot);
        }

        //order button was clicked
        private void OrderClicked(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            OrderType ot = (OrderType)btn.Tag;

            //some orders are one-shot, others require entering command mode
            switch (ot)
            {
                case OrderType.TugRelease:
                case OrderType.GravRelease:
                case OrderType.CreateGate:
                case OrderType.Detonate:
                case OrderType.EjectUDO:
                case OrderType.Launch:
                    btn.Visible = false;
                    SubmitOneShotOrder(ot);
                    break;
                case OrderType.ShipBuildStarShip:
                    GamePage.SidePanelMode = SidePanels.StarShipBuild;
                    break;
                default:
                    GamePage.EnterCommandMode(ot);
                    break;
            }

        }
        private void SubmitOneShotOrder(OrderType ot)
        {
            foreach (StarShip ship in GamePage.ShipsSelected)
                if (ship.CanExecuteOrder(ot))
                    GamePage.SubmitOrder(ot, ship);
        }

        //private members
        private List<OrderType> _ordersVisible = new List<OrderType>();

        //clear orders
        private void btnClearOrders_Click(object sender, EventArgs e)
        {
            btnClearOrders.Visible = false;
            foreach (StarShip ship in GamePage.ShipsSelected)
                GamePage.SubmitOrder(OrderType.ClearOrders, ship);
        }

        //attack adjacent on/off
        private bool _ignoreAttackAdjacent = false;
        private void cbAttackAdjacent_CheckedChanged(object sender, EventArgs e)
        {
            if (_ignoreAttackAdjacent)
            {
                _ignoreAttackAdjacent = false;
                return;
            }
            foreach (StarShip ship in GamePage.ShipsSelected)
                if (ship.CanExecuteOrder(OrderType.AttackAdjacent))
                    GamePage.SubmitOrder(OrderType.AttackAdjacent, ship, cbAttackAdjacent.Checked);
            if (cbAttackAdjacent.Checked)
                MainForm.PlaySound("CheckOn");
            else
                MainForm.PlaySound("CheckOff");
        }

        //exit starship mode
        private void btnExit_Click(object sender, EventArgs e)
        {
            GamePage.SidePanelMode = SidePanels.Blank;
        }
    }
}
